<script>
	import util from 'static/utils/util.js'
	export default {
		data() {
			return {
				delayTimer: null,
				deviceId: '',
				serviceId: '',
				charId: '',
				name: wx.getStorageSync("name") || "00002122868A",
			}
		},
		onLaunch() {
			console.log('App Launch')
		},
		onShow() {
			console.log('App Show', this.globalData)
		},
		onHide() {
			console.log('App Hide')
		},
		methods: {
			toggleTest() {
				this.globalData.test = !this.globalData.test
			},
			async autoLogin() {
				await this.getOpenId()
				await this.wxloginByOpenId()
			},

			async getOpenId() {
				var res = await this.wxLogin();
				//通过 wx.login 接口获得临时登录凭证 code 授权
				var jsCode = res.code
				var url = '/passport/jscode2session'
				var params = {
					jscode: jsCode
				}
				var options = {
					url,
					params
				}
				var param = await util.requestPro(options)
				wx.setStorageSync('openId', param.result.openid);
			},
			wxLogin() {
				return new Promise((resolve, reject) => {
					wx.login({
						complete: (res) => {
							resolve(res)
						},
					})
				})
			},
			async wxloginByOpenId() {
				var openId = wx.getStorageSync('openId');
				var url = '/passport/wxloginByOpenId'
				var params = {
					openId: openId
				}
				var options = {
					url,
					params
				}
				var param = await util.requestPro(options)
				wx.setStorageSync('tokenopen', param.result.token);
			},


			onShowModal() {
				var that = this;
				wx.showModal({
					title: '请打开蓝牙',
					content: '进入微信“我-设置-个人信息与权限-系统权限管理”-蓝牙-连接蓝牙设备-允许使用「蓝牙」打开',
					cancelColor: "#999999",
					confirmColor: "#E7B7C5",
					confirmText: '已打开',
					cancelText: '取消',
					success(res) {
						if (res.confirm) {
							that.initBLE()
						} else if (res.cancel) {}
					}
				})
			},

			//请点击设置按钮打开
			wxgetSetting() {
				var that = this;
				//（1）获取用户授权的信息
				wx.getSetting({
					success(res) {
						console.log('getSetting', res);
						//判断scope.writePhotosAlbum的值，若为true则已经授权
						if (res.authSetting['scope.bluetooth']) {
							that.initBLE();
							//若为undefined，则说明是第一次授权，需要调用wx.authorize弹出授权框，授权框只在第一次询问时弹出，如果用户已经拒绝了，则不会弹出。
						} else if (res.authSetting['scope.bluetooth'] === undefined) {
							wx.authorize({
								scope: 'scope.bluetooth',
								success() {
									that.initBLE();
								},
								fail(res) {
									console.log('authorize-fail', res);
								}
							})
						} else {
							//若为false,则已经拒绝了授权，这时候我们需要调用wx.openSetting引导用户打开设置，保存到相册
							//wx.openSetting,打开小程序设置页,避免此类滥用情况，微信调整了开启方式，button和对话框Modad确认按钮调用wx.openSetting有效
							that.openBlueModel()
						}
					}
				})
			},

			openBlueModel() {
				var that = this;
				wx.showModal({
					title: "温馨提示",
					content: '您没有开启蓝牙授权开关，请点击设置按钮打开',
					confirmText: '去设置',
					confirmColor: "#E7B7C5",
					cancelText: '取消',
					success(res) {
						if (res.confirm) {
							wx.openSetting({
								success(res) {
									if (res.authSetting['scope.bluetooth']) {
										//连接蓝牙
										that.initBLE();
									} else {
										wx.showToast({
											title: '您没有开启蓝牙授权开关',
											icon: 'none'
										})
									}
								},
							})
						}
					},
				})
			},
			//neeFind 是否需要查找设备
			async initBLE(neeFind = true) {
				var that = this;
				this.printLog("启动蓝牙适配器, 蓝牙初始化")
				return new Promise((resolve, reject) => {
					wx.openBluetoothAdapter({
						async success(res) {
							console.log('openBluetoothAdapter=', res);
							resolve(true)
							if (neeFind) {
								await that.findBLE();
							}
						},
						fail(res) {
							console.log("请先打开蓝牙", res);
							that.printLog("请先打开蓝牙" + JSON.stringify(res))
							if (res.errMsg.match(/deny/)) {
								//去检测开启小程序权限开关
								that.wxgetSetting()
							} else if (res.errCode == 10001 || res.errMsg) {
								resolve(false)
								that.onShowModal();
							} else {
								resolve(false)
							}
						}
					})
				})
			},

			printLog(msg) {
				this.globalData.logs.push(msg);
			},
			async findBLE() {
				var that = this;
				return new Promise((resolve, reject) => {
					wx.startBluetoothDevicesDiscovery({
						async success(res) {
							console.log("正在搜索设备", res);
							that.printLog("正在搜索设备")
							that.delayTimer = setInterval(async () => {
								await that.discoveryBLE() //这里的discovery需要多次调用
								resolve()
							}, 1000);
							setTimeout(() => {
								that.closeSearch()
							}, 6000);
						}
					})
				})
			},
			async discoveryBLE() {
				var that = this
				return new Promise((resolve, reject) => {
					wx.getBluetoothDevices({
						async success(res) {
							var list = res.devices;
							console.log(list);
							if (!list.length) {
								return;
							}
							var devices = [];
							for (var i = 0; i < list.length; i++) {
								var name = list[i].name || list[i].localName;
								// 名字为空就跳出循环
								if (!name) {
									continue;
								}
								// 连接的蓝牙设备地址deviceId对于mac地址 "A8:5A:E0:5A:CD:17"
								var deviceId = list[i].deviceId
								var nameFind = "00002122868A"; // 连接的蓝牙设备名称
								var nameFind = that.globalData.name; // 连接的蓝牙设备名称
								// console.log('that.name', that.name, that.globalData.name)
								if (name == nameFind) {
									console.log("找到指定设备", name, list[i]);
									that.printLog("找到指定设备" + name);
									that.closeSearch()
									that.deviceId = deviceId
									that.globalData.deviceId = deviceId
									// that.createBlueDirect(deviceId, name);
									await that.testReconnect();
									resolve()
									break;
								}
							}
						},
						fail() {
							console.log("搜索蓝牙设备失败");
							that.printLog("搜索蓝牙设备失败");
						}
					})
				})
			},
			closeSearch() {
				var that = this
				if (that.delayTimer) {
					clearInterval(that.delayTimer);
					that.delayTimer = null
					wx.stopBluetoothDevicesDiscovery({
						success(res) {
							that.printLog('连接蓝牙成功之后关闭蓝牙搜索');
						}
					})
				}
			},

			//测试重新连接，并发握手指令
			async testReconnect() {
				var that = this;
				await this.closeBLE(this.globalData.deviceId)
				console.log("预先关闭之前的连接，再打开新的蓝牙连接");
				return new Promise((resolve, reject) => {
					setTimeout(async () => {
						await this.createBlueDirect(this.globalData.deviceId, this.globalData.name)
						resolve()
					}, 300)
				})

			},
			// 只连接设备，不发指令
			async testConnectStatus() {
				var that = this;
				await this.closeBLE(this.globalData.deviceId)
				console.log("预先关闭之前的连接，再打开新的蓝牙连接");
				return new Promise((resolve, reject) => {
					setTimeout(async () => {
						var isConnect = await that.createBLEConnect(this.globalData.deviceId)
						console.log('testConnectStatus-isConnect', isConnect)
						that.globalData.isConnect = isConnect
						resolve(isConnect)
					}, 300)
				})

			},
			async testOpenDoor(door = 1) {
				var that = this;
				await this.closeBLE(this.globalData.deviceId)
				console.log("预先关闭之前的连接，再打开新的蓝牙连接");
				return new Promise((resolve, reject) => {
					setTimeout(async () => {
						await this.createBlueDirect(this.globalData.deviceId, this.globalData.name,
							door)
						util.toast('开门成功')
						resolve(true)
					}, 300)
				})
			},
			closeBLE(deviceId) {
				var that = this;
				return new Promise((resolve, reject) => {
					wx.closeBLEConnection({
						deviceId: deviceId,
						success(res) {
							that.printLog("断开设备[" + deviceId + "]成功.");
							console.log(res)
						},
						fail(res) {
							that.printLog("断开设备成功.");
						},
						complete() {
							resolve()
						}
					})
				})

			},

			async createBlueDirect(deviceId, name, door) {
				var that = this;
				this.printLog("连接: [" + name + '-' + deviceId + "]");
				console.log("连接: [" + name + '-' + deviceId + "]");
				var isConnect = await that.createBLEConnect(deviceId)
				that.globalData.isConnect = isConnect
				var serviceId = await that.getBLEServiceId(deviceId)
				var charId = await that.getBLECharactedId(deviceId, serviceId);
				//发送连接握手指令
				var buffer = that.connectCode(name)
				await that.writeBLE(deviceId, serviceId, charId, buffer)
				return new Promise((resolve, reject) => {
					if (door) {
						//延时0.5秒后，发送开门
						setTimeout(async () => {
							var bufferDoor = that.openCode(name, door)
							await that.writeBLE(deviceId, serviceId, charId, bufferDoor)
							resolve()
						}, 500)
					} else {
						resolve()
					}
				})

			},

			createBLEConnect(deviceId) {
				var that = this;
				return new Promise((resolve, reject) => {
					wx.createBLEConnection({
						deviceId: deviceId,
						success(res) {
							that.printLog("设备连接成功");
							console.log("设备连接成功");
							resolve(true)
						},
						fail(res) {
							that.printLog("设备连接失败", res);
							console.log("设备连接失败", res);
							util.toast("设备连接失败");
							resolve(false)
						}
					})
				})
			},

			//获取服务UUID
			getBLEServiceId(deviceId) {
				this.printLog("获取设备[" + deviceId + "]服务列表")
				var that = this;
				return new Promise((resolve, reject) => {
					wx.getBLEDeviceServices({
						deviceId: deviceId,
						success(res) {
							var services = res.services;
							console.log('services', services);
							if (services.length <= 0) {
								that.printLog("未找到主服务列表")
								return;
							}
							that.printLog('找到设备服务列表个数: ' + services.length);
							if (services.length) {
								var service = services[0];
								var serviceId = service.uuid
								that.serviceId = serviceId
								console.log("服务UUID:[" + serviceId + "] Primary:" + service.isPrimary);
								that.printLog("服务UUID:[" + serviceId + "] Primary:" + service
									.isPrimary);
								// that.getBLECharactedId(deviceId, serviceId);
								resolve(serviceId)
							}
						},
						fail(res) {
							that.printLog("获取设备服务列表失败" + res.errMsg);
						}
					})
				})
			},

			getBLECharactedId(deviceId, serviceId) {
				this.printLog("获取设备特征值")
				var that = this;
				return new Promise((resolve, reject) => {
					wx.getBLEDeviceCharacteristics({
						deviceId: deviceId,
						serviceId: serviceId,
						success(res) {
							console.log(res);
							//这里会获取到两个特征值，一个用来写，一个用来读
							var chars = res.characteristics;
							if (chars.length <= 0) {
								that.printLog("未找到设备特征值")
								return;
							}
							that.printLog("找到设备特征值个数:" + chars.length);
							if (chars.length == 2) {
								for (var i = 0; i < chars.length; i++) {
									var char = chars[i];
									that.printLog("特征值[" + char.uuid + "]")
									var prop = char.properties;
									if (prop.notify) {
										that.printLog("该特征值属性: Notify");
										that.recvBLECharacterNotice(deviceId, serviceId, char.uuid);
									} else if (prop.write) {
										that.printLog("该特征值属性: Write");
										resolve(char.uuid)
									} else {
										that.printLog("该特征值属性: 其他");
									}
								}
							}
						},
						fail(res) {
							that.printLog("获取设备特征值失败")
						}
					})
				})
			},

			//接收设置是否成功
			recvBLECharacterNotice(deviceId, serviceId, charId) {
				this.printLog("注册Notice 回调函数");
				var that = this;
				wx.notifyBLECharacteristicValueChange({
					deviceId: deviceId,
					serviceId: serviceId,
					characteristicId: charId,
					state: true, //启用Notify功能
					success(res) {
						wx.onBLECharacteristicValueChange(function(res) {
							var strCode = that.ab2hex(res.value)
							console.log("收到Notify数据: " + strCode);
							that.printLog("收到Notify数据: " + strCode);
							// 返回的值ff550e023200002122868a01158f
							//0115 0x01:电机到位 0x15电池电量5格
							var battery = strCode.match(/011(\d{1})/)
							if (battery && !that.globalData.battery) {
								that.globalData.battery = battery[1]
								console.log('battery', battery)
								that.printLog('电量：', battery)
							}
						});
					},
					fail(res) {
						console.log(res);
						that.printLog("特征值Notice 接收数据失败: " + res.errMsg);
					}
				})
			},

			writeBLE(deviceId, serviceId, charId, buffer) {
				var that = this
				console.log("发送指令=" + that.ab2hex(buffer));
				return new Promise((resolve, reject) => {
					wx.writeBLECharacteristicValue({
						deviceId: deviceId,
						serviceId: serviceId,
						characteristicId: charId,
						value: buffer,
						success(res) {
							that.printLog("发送指令成功" + that.ab2hex(buffer));
							console.log("发送指令成功" + that.ab2hex(buffer));
							resolve()
						},
						fail(res) {
							console.log(res);
							that.printLog("发送失败." + res.errMsg);
						},
					})
				})
			},

			//连接握手指令拼接
			connectCode(str = "00002122868A") {
				var arr1 = [0xFF, 0x55, 0x12, 0x01, 0x05]
				//00002122868A转换成[0x00, 0x00, 0x21, 0x22, 0x86, 0x8A]
				var arr2 = str.match(/[\da-f]{2}/gi).map((item) => parseInt(item, 16))
				var arr3 = [0x01, 0x6C, 0x6F, 0x67, 0x69, 0x6E]
				var arr = [].concat(arr1, arr2, arr3)
				//对上面的数组每个值进行异或运算得到异或校验值
				var hex = arr.reduce((pre, cur) => pre ^ cur)
				//添加到数组末端
				arr.push(hex)
				console.log('连接握手指令:', this.ab2hexString(arr))
				return this.getBuffer(arr)
			},

			//开门指令拼接
			openCode(str = "00002122868A", door = 1) {
				var arr1 = [0xFF, 0x55, 0x12, 0x01, 0x05]
				//00002122868A转换成[0x00, 0x00, 0x21, 0x22, 0x86, 0x8A]
				var arr2 = str.match(/[\da-f]{2}/gi).map((item) => parseInt(item, 16))
				var arr3 = [0x02, 0x00, 0x00, 0x01, 0x00, 0x00]
				//动态替换指定的门
				var doorHex = parseInt(door, 16) //1 => 0x01
				arr3[3] = doorHex
				var arr = [].concat(arr1, arr2, arr3)
				//对上面的数组每个值进行异或运算得到异或校验值
				var hex = arr.reduce((pre, cur) => pre ^ cur)
				//添加到数组末端
				arr.push(hex)
				return this.getBuffer(arr)
			},

			// 16进制数字数组转换成=>ArrayBufer
			getBuffer(arr) {
				var buffer = new ArrayBuffer(arr.length)
				var dataView = new DataView(buffer)
				for (var i = 0; i < arr.length; i++) {
					dataView.setUint8(i, arr[i])
				}
				return buffer
			},

			//将16进制数字数组转换成字符串
			ab2hexString(arr) {
				arr = arr instanceof Array ? arr : Array.from(arr)
				var hexArr = arr.map(item => {
					//高位补00,处理0的情况，0x00.toString(16)=0
					var item = '00' + item.toString(16)
					return item.slice(-2)
				})
				return hexArr.join('');
			},
			//将ArrayBuffer转换成字符串
			ab2hex(buffer) {
				var arr = new Uint8Array(buffer)
				return this.ab2hexString(arr)
			},
			//将ArrayBuffer转换成字符串
			ab2hex(buffer) {
				var hexArr = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {
						return ('00' + bit.toString(16)).slice(-2)
					}
				)
				return hexArr.join('');
			},

		},
		globalData: {
			name: wx.getStorageSync("name") || "00002122868A",
			logs: [],
			battery: 0,
			deviceId: '',
			isConnect: false,
			test: true,

		}
	}
</script>

<style>
	/*每个页面公共css */
	@import url("./style/common.css");

	/* 	button {
		padding: 0;
	} */
	button::after {
		border: 0 !important;
	}
</style>
